package com.yundingai.service.impl;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.yundingai.common.DocumentAnalysisException;
import lombok.extern.slf4j.Slf4j;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.stereotype.Service;
import org.xml.sax.ContentHandler;
import reactor.core.publisher.Flux;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

/**
 * @Author HuangZhengmin
 * @desc 文件分析服务 结合Minio存储和AI服务进行文件内容分析
 * @Date 2025/7/17 12:18
 * @Version 1.0
 */
@Slf4j
@Service
public class FileAnalysisService {
  /// AI客户端
  private final ChatClient chatClient;

// 自动注入ChatClient.Builder，并构建ChatClient
  @Autowired
  public FileAnalysisService(ChatClient.Builder chatClientBuilder) {
    // 使用ChatClient.Builder构建ChatClient
    this.chatClient = chatClientBuilder.build();
  }

  /**
   * 分析文件内容
   * @param fileData 文件字节数据
   * @return AI分析结果
   */
  public String analyzeFileContent(byte[] fileData) {
    try {
      // 1. 提取文件内容
      String content = extractContent(fileData);

      // 2. 调用AI服务分析内容
      return analyzeContent(content);

    } catch (Exception e) {
      throw new RuntimeException("文件分析失败", e);
    }
  }

  /**
   * 从文件字节数据中提取文本内容
   */
  private String extractContent(byte[] fileData) throws IOException, TikaException {
    AutoDetectParser parser = new AutoDetectParser();
    ContentHandler handler = new BodyContentHandler(-1); // -1表示不限制内容长度
    Metadata metadata = new Metadata();
    ParseContext context = new ParseContext();

    try (InputStream stream = new ByteArrayInputStream(fileData)) {
      parser.parse(stream, handler, metadata, context);
      String content = handler.toString();

      if (StringUtils.isEmpty(content)) {
        throw new UnsupportedOperationException("无法从文件中提取文本内容");
      }

      return content;
    } catch (Exception e) {
      throw new TikaException("文件解析失败: " + e.getMessage(), e);
    }
  }

  /**
   * 从图片中提取文本（OCR）
   */
  private String extractTextFromImage(byte[] imageData) {
    // 实际项目中应集成Tesseract等OCR引擎
    return "[图片内容待OCR识别]";
  }

  /**
   * 调用AI服务分析文本内容
   */
  private String analyzeContent(String content) {
    return chatClient.prompt()
            .user("请分析以下内容:\n" + content)
            .call()
            .content();
  }

  /**
   * 流式分析文件内容
   * @param fileData 文件字节数据
   * @return ServerSentEvent流
   */
  public Flux<ServerSentEvent<String>> streamAnalyzeFile(byte[] fileData) {
    try {
      log.debug("开始解析文件，文件大小: {} bytes", fileData.length);
      String content = extractContent(fileData);
      log.debug("提取内容长度: {} 字符", content.length());

      return streamAnalyzeContent(content)
              .doOnError(e -> log.error("流式分析过程中出错", e));

    } catch (Exception e) {
      log.error("文件解析失败", e);
      return Flux.error(new RuntimeException("无法解析文件: " + e.getMessage()));
    }
  }

  /**
   * 流式分析文本内容
   */
  private Flux<ServerSentEvent<String>> streamAnalyzeContent(String content) {
    return chatClient.prompt()
            .user("请分析以下内容:\n" + content)
            .stream()
            .content()
            .map(text -> ServerSentEvent.builder(text).build())
            .onErrorResume(e -> Flux.error(new RuntimeException("AI分析失败", e)));
  }

  /**
   * 根据用户需求处理文件内容
   */
  public Flux<ServerSentEvent<String>> processFileContent(byte[] fileData, String userRequest) {
    try {
      // 1. 提取文件内容
      String content = extractContent(fileData);

      // 2. 构建提示词 - 将用户需求与文件内容结合
      String prompt = buildPrompt(userRequest, content);

      log.info("处理用户需求, 提示词: {}", prompt);

      // 3. 调用AI服务处理
      return chatClient.prompt()
              .user(prompt)
              .stream()
              .content()
              .map(text -> ServerSentEvent.builder(text)
                      .id(UUID.randomUUID().toString())
                      .event("message")
                      .build())
              .onErrorResume(e -> {
                log.error("AI处理失败", e);
                return Flux.just(ServerSentEvent.<String>builder()
                        .event("error")
                        .data("AI处理失败: " + e.getMessage())
                        .build());
              });

    } catch (Exception e) {
      log.error("文件处理失败", e);
      return Flux.error(new DocumentAnalysisException("文件处理失败: " + e.getMessage()));
    }
  }

  /**
   * 构建智能提示词
   */
  private String buildPrompt(String userRequest, String fileContent) {
    return String.format("""
                用户需求: %s
                
                文档内容:
                %s
                
                请根据用户需求处理上述文档内容，提供专业、准确的响应。
                注意: 
                1. 如果用户需求涉及摘要，请提供关键点总结
                2. 如果用户需求涉及数据分析，请提取相关数据并分析
                3. 如果用户需求不明确，请主动询问澄清问题
                """, userRequest, fileContent);
  }
  /**
   * 流式聊天处理
   * @param message 用户消息
   * @return ServerSentEvent流
   */
  public Flux<ServerSentEvent<String>> streamChat(String message) {
    return chatClient.prompt()
            .user(message)
            .stream()
            .content()
            .map(text -> ServerSentEvent.builder(text).build());
  }

}